using System;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
using static WinApi;
using System.Runtime.InteropServices;

public class User32Controller : IDisposable
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
    IntPtr _hwnd = IntPtr.Zero;
    Rect _originalRect;

    IntPtr _originalWndProc = IntPtr.Zero;
    WNDPROC _customWndProc;

    #region 常量
    const int WM_SIZE = 0x0005;
    const int SIZE_RESTORED = 0;
    const int SIZE_MINIMIZED = 1;
    const int SIZE_MAXIMIZED = 2;
    const int SW_MAXIMIZE = 3;
    const int SW_MINIMIZE = 6;
    const int SW_RESTORE = 9;
    const int GWL_STYLE = -16;
    const int GWL_WNDPROC = -4;

    const uint SWP_NOSIZE = 0x0001;
    const uint SWP_NOMOVE = 0x0002;
    const uint SWP_NOZORDER = 0x0004;
    const uint SWP_NOACTIVATE = 0x0010;
    const uint SWP_FRAMECHANGED = 0x0020;

    const uint MONITOR_DEFAULTTONEAREST = 0x00000002;

    const uint WM_SYSCOMMAND = 0x0112;
    const uint WM_DPICHANGED = 0x02E0;
    const uint WM_GETMINMAXINFO = 0x0024;
    const int SC_MAXIMIZE = 0xF030;
    const int SC_RESTORE = 0xF120;
    const int SC_MINIMIZE = 0xF020;
    const uint WM_NCLBUTTONDBLCLK = 0x00A3;

    const uint WM_NCCALCSIZE = 0x0083;
    const uint WM_NCHITTEST = 0x0084;
    const uint HTCLIENT = 0x01;
    const uint HTCAPTION = 0x02;
    const uint HTLEFT = 0x0A;
    const uint HTRIGHT = 0x0B;
    const uint HTBOTTOM = 0x0F;
    const uint HTBOTTOMLEFT = 0x10;
    const uint HTBOTTOMRIGHT = 0x11;
    const int WS_CAPTION = 0x00C00000;
    const int WS_THICKFRAME = 0x00040000;
    const uint WM_EXITSIZEMOVE = 0x0232; // 新增：用户完成拖拽/调整大小

    // DWM 常量
    const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;

    #endregion

    public User32Controller()
    {
        _hwnd = GetUnityMainWindowHandle();

        if (_hwnd == IntPtr.Zero)
        {
            Debug.LogError("User32Controller: 无法找到合适的 Unity 窗口句柄。");
            return;
        }

        if (GetWindowRect(_hwnd, out RECT r))
            _originalRect = r.ToRect();

        _customWndProc = new WNDPROC(CustomWindowProc);
        _originalWndProc = SetWindowLongPtr(_hwnd, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(_customWndProc));

        ApplyBorderlessStyleWithDwmFix();
    }

    IntPtr GetUnityMainWindowHandle()
    {
        int processId = Process.GetCurrentProcess().Id;
        IntPtr hWnd = IntPtr.Zero;

        EnumWindows((hWnd1, lParam) =>
        {
            if (IsWindowVisible(hWnd1))
            {
                GetWindowThreadProcessId(hWnd1, out ulong windowProcessId);
                if (windowProcessId == (ulong)processId)
                {
                    hWnd = hWnd1;
                    return false;
                }
            }
            return true;
        }, IntPtr.Zero);

        return hWnd;
    }

    private void ApplyBorderlessStyleWithDwmFix()
    {
        if (_hwnd == IntPtr.Zero) return;

        int style = GetWindowLong(_hwnd, GWL_STYLE);
        style &= ~WS_CAPTION;
        style |= WS_THICKFRAME;
        SetWindowLong(_hwnd, GWL_STYLE, style);

        SetWindowPos(_hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    }

    public Action CallStatusChanged;
    bool _isMaximized = false;
    public bool IsMaximized
    {
        get => _isMaximized;
        set
        {
            _isMaximized = value;
            CallStatusChanged?.Invoke();
        }
    }

    private IntPtr CustomWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
        if (msg == WM_NCHITTEST)
        {
            IntPtr defaultHit = CallWindowProc(_originalWndProc, hWnd, msg, wParam, lParam);
            return HandleNCHitTest(lParam, defaultHit);
        }

        //----------------------------------------------------
        // 3) 阻止 DPI 自适应（防止分辨率跳变）
        //----------------------------------------------------
        if (msg == WM_DPICHANGED)
        {
            return IntPtr.Zero; // 不让系统调整窗口大小
        }

        // 只在用户完成手动调整后保存尺寸
        if (msg == WM_EXITSIZEMOVE)
        {
            // 用户完成了拖拽或手动调整大小
            if (!IsZoomed(_hwnd) && !IsIconic(_hwnd)) // 确保不是最大化或最小化状态
            {
                if (GetWindowRect(_hwnd, out RECT rect))
                {
                    _originalRect = rect.ToRect();
                }
            }
        }
        if (msg == WM_SYSCOMMAND)
        {
            int cmd = wParam.ToInt32() & 0xFFF0;

            if (cmd == SC_MAXIMIZE)
            {
                Maximize();
                return IntPtr.Zero;
            }
            else if (cmd == SC_RESTORE)
            {
                Restore();
                return IntPtr.Zero;
            }
        }

        if (msg == WM_SIZE)
        {
            int sizingType = wParam.ToInt32();
            if (sizingType == SIZE_MAXIMIZED)
            {
                if (!_isMaximized)
                {
                    Maximize();
                }
            }
            else if (sizingType == SIZE_RESTORED)
            {
                if (_isMaximized)
                {
                    Restore();
                }
            }
        }

        unsafe
        {
            if (msg == WM_NCCALCSIZE && wParam != IntPtr.Zero)
            {
                NCCALCSIZE_PARAMS* p = (NCCALCSIZE_PARAMS*)lParam;
                RECT rect = p->GetRect(0);
                rect.top += 4;
                p->SetRect(0, rect);
                return IntPtr.Zero;
            }
        }

        if (msg == WM_NCLBUTTONDBLCLK)
        {
            if (IsMaximized)
            {
                Restore();
            }
            else
            {
                Maximize();
            }
            return IntPtr.Zero;
        }



        if (msg == WM_GETMINMAXINFO)
        {
            if (GetWindowRect(hWnd, out RECT rect))
            {
                POINT center = new POINT { X = (rect.left + rect.right) / 2, Y = (rect.top + rect.bottom) / 2 };
                IntPtr hMonitor = MonitorFromPoint(center, MONITOR_DEFAULTTONEAREST);
                if (hMonitor != IntPtr.Zero)
                {
                    MONITORINFO info = new MONITORINFO();
                    info.cbSize = Marshal.SizeOf(info);
                    if (GetMonitorInfo(hMonitor, ref info))
                    {
                        MINMAXINFO mmi = Marshal.PtrToStructure<MINMAXINFO>(lParam);

                        mmi.ptMaxSize.X = info.rcWork.right - info.rcWork.left;
                        mmi.ptMaxSize.Y = info.rcWork.bottom - info.rcWork.top;
                        mmi.ptMaxPosition.X = info.rcWork.left;
                        mmi.ptMaxPosition.Y = info.rcWork.top;

                        Marshal.StructureToPtr(mmi, lParam, false);
                        return IntPtr.Zero;
                    }
                }
            }
        }
        return CallWindowProc(_originalWndProc, hWnd, msg, wParam, lParam);
    }

    bool IsWindowMaximizedState(IntPtr hWnd)
    {
        return IsZoomed(hWnd);
    }
    IntPtr HandleNCHitTest(IntPtr lParam, IntPtr defaultHit)
    {
        if (!GetWindowRect(_hwnd, out RECT rect)) return IntPtr.Zero;

        int x = (short)(lParam.ToInt32() & 0xFFFF);
        int y = (short)((lParam.ToInt32() >> 16) & 0xFFFF);
        int localY = y - rect.top;
        int localX = x - rect.left;
        int windowWidth = rect.right - rect.left;
        int windowHeight = rect.bottom - rect.top; // 添加高度计算
        int borderSize = 10; // 边缘宽度
        int cornerSize = 10; // 角落区域大小

        // 左上角
        if (localX >= 0 && localX < cornerSize && localY >= 0 && localY < cornerSize)
            return defaultHit;
        // 右上角
        if (localX >= windowWidth - cornerSize && localX < windowWidth && localY >= 0 && localY < cornerSize)
            return defaultHit;
        // 左下角
        if (localX >= 0 && localX < cornerSize && localY >= windowHeight - cornerSize && localY < windowHeight)
            return (IntPtr)HTBOTTOMLEFT;
        // 右下角
        if (localX >= windowWidth - cornerSize && localX < windowWidth && localY >= windowHeight - cornerSize && localY < windowHeight)
            return (IntPtr)HTBOTTOMRIGHT;

        // --- 2. 然后判断四条边缘 ---
        // 上边
        if (localX >= 0 && localY < borderSize)
            return defaultHit;
        // 下边
        if (localY >= windowHeight - borderSize && localY < windowHeight)
            return (IntPtr)HTBOTTOM;
        // 左边
        if (localX >= 0 && localX < borderSize)
            return (IntPtr)HTLEFT;
        // 右边
        if (localX >= windowWidth - borderSize && localX < windowWidth)
            return (IntPtr)HTRIGHT;

        // --- 3. 最后判断标题栏区域 ---
        if (localY >= 0 && localY < 50) // 保持原来的标题栏高度判断
        {
            if (IsSimulation)
            {
                bool inForbiddenZone1 = localX >= windowWidth * 0.49f && localX <= windowWidth * 0.59f;
                bool inForbiddenZone2 = localX > windowWidth - 420;
                if (!inForbiddenZone1 && !inForbiddenZone2)
                {
                    return (IntPtr)HTCAPTION;
                }
            }
            else
            {
                bool isLeftButtonArea = localX < 300;
                bool isRightButtonArea = localX > (windowWidth - 120);
                if (!isLeftButtonArea && !isRightButtonArea)
                {
                    return (IntPtr)HTCAPTION;
                }
            }
        }

        // 默认返回 HTCLIENT
        return (IntPtr)HTCLIENT;
    }

    // ---------- Maximize() 改进版 ----------
    public void Maximize()
    {
        if (_hwnd == IntPtr.Zero || _isMaximized) return;

        // 保存当前 normal rect
        if (!IsZoomed(_hwnd) && !IsIconic(_hwnd))
        {
            if (GetWindowRect(_hwnd, out RECT currentRect))
                _originalRect = currentRect.ToRect();
        }
        // 2) 获取 monitor 的 rcMonitor（注意：rcMonitor 而不是 rcWork）
        IntPtr hMon = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST);
        if (hMon != IntPtr.Zero)
        {
            MONITORINFO mi = new MONITORINFO { cbSize = Marshal.SizeOf<MONITORINFO>() };
            if (GetMonitorInfo(hMon, ref mi))
            {
                RECT m = mi.rcWork;

                // 3) 强制设置窗口到 rcMonitor（覆盖任何系统保留）
                SetWindowPos(_hwnd, IntPtr.Zero,
                    m.left, m.top,
                    m.right - m.left, m.bottom - m.top,
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);

                IsMaximized = true;
                return;
            }
        }

        // 兜底
        ShowWindow(_hwnd, SW_MAXIMIZE);
        IsMaximized = true;
    }

    public void Restore()
    {
        if (_hwnd == IntPtr.Zero) return;

        ShowWindow(_hwnd, SW_RESTORE);

        if (_originalRect.width > 0 && _originalRect.height > 0)
        {
            SetWindowPos(_hwnd, IntPtr.Zero,
                        (int)_originalRect.x, (int)_originalRect.y,
                        (int)_originalRect.width, (int)_originalRect.height,
                        SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
        }
        else
        {
            IntPtr hMonitor = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST);
            MONITORINFO mi = new MONITORINFO { cbSize = Marshal.SizeOf<MONITORINFO>() };
            if (hMonitor != IntPtr.Zero && GetMonitorInfo(hMonitor, ref mi))
            {
                RECT workArea = mi.rcWork;
                int w = Math.Min(1280, (int)((workArea.right - workArea.left) * 0.8));
                int h = Math.Min(720, (int)((workArea.bottom - workArea.top) * 0.8));
                int x = workArea.left + (workArea.right - workArea.left - w) / 2;
                int y = workArea.top + (workArea.bottom - workArea.top - h) / 2;
                _originalRect = new Rect(x, y, w, h);

                SetWindowPos(_hwnd, IntPtr.Zero, x, y, w, h,
                            SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
            }
            else
            {
                int screenWidth = GetSystemMetrics(SIZE_RESTORED);
                int screenHeight = GetSystemMetrics(SIZE_MINIMIZED);
                int x = (screenWidth - 1280) / 2;
                int y = (screenHeight - 720) / 2;
                _originalRect = new Rect(x, y, 1280, 720);
                SetWindowPos(_hwnd, IntPtr.Zero, x, y, 1280, 720,
                            SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
            }
        }

        IsMaximized = false;
    }

    public void Minimize()
    {
        if (_hwnd == IntPtr.Zero) return;
        ShowWindow(_hwnd, SW_MINIMIZE);
    }

    public void Dispose()
    {
        if (_hwnd != IntPtr.Zero && _originalWndProc != IntPtr.Zero)
        {
            SetWindowLongPtr(_hwnd, GWL_WNDPROC, _originalWndProc);
        }
        _hwnd = IntPtr.Zero;
    }

    internal void SetTopColor(bool v)
    {
        int darkMode = v ? 1 : 0;
        DwmSetWindowAttribute(_hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
                   ref darkMode, sizeof(int));
    }

    bool IsSimulation;
    internal void SetIsSimulation(bool v)
    {
        IsSimulation = v;
    }
#endif
}
